package com.jingdianjichi.subject.domain.service.impl;

import com.jingdianjichi.subject.common.enums.IsDeletedFlagEnum;
import com.jingdianjichi.subject.domain.config.ThreadPoolConfig;
import com.jingdianjichi.subject.domain.convert.SubjectCategoryBOConverter;
import com.jingdianjichi.subject.domain.entity.SubjectCategoryBO;
import com.jingdianjichi.subject.domain.entity.SubjectLabelBO;
import com.jingdianjichi.subject.domain.service.SubjectCategoryDomainService;
import com.jingdianjichi.subject.infra.basic.entity.SubjectCategory;
import com.jingdianjichi.subject.infra.basic.entity.SubjectLabel;
import com.jingdianjichi.subject.infra.basic.entity.SubjectMapping;
import com.jingdianjichi.subject.infra.basic.service.SubjectCategoryService;
import com.jingdianjichi.subject.infra.basic.service.SubjectLabelService;
import com.jingdianjichi.subject.infra.basic.service.SubjectMappingService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SubjectCategoryDomainServiceImpl implements SubjectCategoryDomainService {

    @Resource
    private SubjectCategoryService subjectCategoryService;

    @Resource
    private SubjectLabelService subjectLabelService;

    @Resource
    private SubjectMappingService subjectMappingService;

    @Resource
    private ThreadPoolExecutor labelThreadPool;


    @Override
    public void add(SubjectCategoryBO subjectCategoryBO) {
//        if(log.isInfoEnabled()){
//            log.info("SubjectCategoryDomainServiceImpl.add.subjectCategoryBO",subjectCategoryBO);
//        }
        SubjectCategory subjectCategory = SubjectCategoryBOConverter
                .Instance.BOToSubjectCategory(subjectCategoryBO);
        subjectCategory.setIsDeleted(IsDeletedFlagEnum.UNDELETED.getCode());
        subjectCategoryService.insert(subjectCategory);
    }

    @Override
    public List<SubjectCategoryBO> queryCategory(SubjectCategoryBO subjectCategoryBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectCategoryDomainServiceImpl.queryPrimaryCategory.subjectCategoryBO:{}", subjectCategoryBO);
        }

        SubjectCategory subjectCategory = SubjectCategoryBOConverter.
                Instance.BOToSubjectCategory(subjectCategoryBO);
        subjectCategory.setIsDeleted(IsDeletedFlagEnum.UNDELETED.getCode());

        List<SubjectCategory> subjectCategoryList = subjectCategoryService.queryByCategory(subjectCategory);
        List<SubjectCategoryBO> boList = SubjectCategoryBOConverter.
                Instance.subjectboList(subjectCategoryList);

        boList.forEach(bo -> {
            Integer count = subjectCategoryService.queryBySubjectCount(bo.getId());
            bo.setCount(count);
        });
        return boList;
    }

    @Override
    public Boolean update(SubjectCategoryBO subjectCategoryBO) {
        SubjectCategory subjectCategory = SubjectCategoryBOConverter.
                Instance.BOToSubjectCategory(subjectCategoryBO);
        int count = subjectCategoryService.update(subjectCategory);
        return count > 0 ? true : false;
    }

    @SneakyThrows
    @Override
    public List<SubjectCategoryBO> queryCategoryandLabel(SubjectCategoryBO subjectCategoryBO) {

        //查询当前大类下所有分类
        SubjectCategory subjectCategory = new SubjectCategory();
        subjectCategory.setId(subjectCategoryBO.getId());
        subjectCategory.setIsDeleted(IsDeletedFlagEnum.UNDELETED.getCode());

        List<SubjectCategory> subjectCategoryList = subjectCategoryService.queryByCategory(subjectCategory);

        List<SubjectCategoryBO> boList = SubjectCategoryBOConverter.
                Instance.subjectboList(subjectCategoryList);

        //线程池并发调用
        List<FutureTask<Map<Long, List<SubjectLabelBO>>>> futureTaskList = new LinkedList<>();
        Map<Long, List<SubjectLabelBO>> listMap = new HashMap<>();

        //一次性获取标签信息
        boList.forEach(bo -> {

            FutureTask<Map<Long, List<SubjectLabelBO>>> futureTask = new FutureTask<>(() ->
                    getLabelBOList(bo));
            futureTaskList.add(futureTask);
            labelThreadPool.submit(futureTask);
        });

        System.out.println(futureTaskList + "......");

        for (FutureTask<Map<Long, List<SubjectLabelBO>>> futureTask : futureTaskList) {
            Map<Long, List<SubjectLabelBO>> resultMap = futureTask.get();
            if (CollectionUtils.isEmpty(resultMap)) {
                continue;
            }
            listMap.putAll(resultMap);
        }

        System.out.println(listMap + "....");

        boList.forEach(bo -> {
            bo.setLabelBOList(listMap.get(bo.getId()));
        });

        return boList;
    }

    private Map<Long, List<SubjectLabelBO>> getLabelBOList(SubjectCategoryBO bo) {

        Map<Long, List<SubjectLabelBO>> map = new HashMap<>();

        SubjectMapping subjectMapping = new SubjectMapping();
        subjectMapping.setCategoryId(bo.getId());
        subjectMapping.setIsDeleted(IsDeletedFlagEnum.UNDELETED.getCode());
        List<SubjectMapping> mappingList = subjectMappingService.queryLabelId(subjectMapping);

        if (CollectionUtils.isEmpty(mappingList)) {
            return null;
        }

        List<Long> labelIdList = mappingList.stream().
                map(SubjectMapping::getLabelId).collect(Collectors.toList());
        List<SubjectLabel> labelList = subjectLabelService.batchQueryById(labelIdList);
        List<SubjectLabelBO> labelBOList = new LinkedList<>();

        labelList.forEach(label -> {
            SubjectLabelBO subjectLabelBO = new SubjectLabelBO();
            subjectLabelBO.setLabelName(label.getLabelName());
            subjectLabelBO.setCategoryId(label.getCategoryId());
            subjectLabelBO.setSortNum(label.getSortNum());
            labelBOList.add(subjectLabelBO);
        });
        map.put(bo.getId(), labelBOList);
        return map;
    }
}
